// -*-c++-*- Copyright (C) 2011 osgPango Development Team
// $Id: TextTransform 169 2012-02-09 00:17:40Z cubicool $

#ifndef OSGPANGO_TEXT_TRANSFORM
#define OSGPANGO_TEXT_TRANSFORM

#include <osg/MatrixTransform>
#include <osgPango/Text>

namespace osgPango {

class OSGPANGO_EXPORT TextTransform: public Text, public osg::MatrixTransform {
public:
	META_Object(osgPango, TextTransform);

	//! These are the alignment enums within TextInterface (not Text itself, since
	//! Text is virtual and has no way of positioning itself) that define how the
	//! text is arranged RELATIVE TO ITS POSITION. They're pretty much
	//! self-explanatory so I won't document each one individually.
	enum PositionAlignment {
		POS_ALIGN_LEFT_TOP,
		POS_ALIGN_LEFT_BOTTOM,
		POS_ALIGN_LEFT_CENTER,
		POS_ALIGN_RIGHT_TOP,
		POS_ALIGN_RIGHT_CENTER,
		POS_ALIGN_RIGHT_BOTTOM,
		POS_ALIGN_CENTER_TOP,
		POS_ALIGN_CENTER_CENTER,
		POS_ALIGN_CENTER_BOTTOM,
		POS_ALIGN_LEFT_BASE_LINE,
		POS_ALIGN_CENTER_BASE_LINE,
		POS_ALIGN_RIGHT_BASE_LINE
	};

	enum AxisAlignment { 
		AXIS_ALIGN_XY_PLANE, 
		AXIS_ALIGN_REVERSED_XY_PLANE, 
		AXIS_ALIGN_XZ_PLANE, 
		AXIS_ALIGN_REVERSED_XZ_PLANE, 
		AXIS_ALIGN_YZ_PLANE, 
		AXIS_ALIGN_REVERSED_YZ_PLANE, 
	};
	
	enum CoordinateAlign {
		//! Request pixel-alignment if the scale is an integral value such as 1.0f,
		//! 2.0f, 3.0f, etc; that is to say, there is no remainder when the scale
		//! is divided by the integer cast of itself.
		COORDINATE_ALIGN_AUTO,

		//! Never pixel-align.
		COORDINATE_ALIGN_NONE,

		//! Always pixel-align.
		COORDINATE_ALIGN_ALWAYS
	};

	TextTransform(ColorMode cm = COLOR_MODE_MARKUP_OVERWRITE);
	TextTransform(const TextTransform& tt, const osg::CopyOp& copyOp);

	//! Necessary override required by Text; it's purpose is to commit
	//! any and all text changes internally and ready the object for display.
	//! If you call addText() dynamically, you will need to also call
	//! finalize() to refresh your changes. This is not true, however,
	//! if you only adjust the position or alignment; as long as the text
	//! doesn't change, there is no need to call finalize().
	virtual bool finalize();

	//! Clears all internal state and data.
	virtual void clear();

	//! This method sets the Matrix in the parent MatrixTransform class.
	virtual void calculatePosition();

	//! Performs some tests to determine (based on the CoordinateAlign) whether
	//! or not this should be coordinate-aligned (pixel aligned).
	bool isCoordinateAligned() const;

	//! Returns the PositionAlignment enum currently in use.
	PositionAlignment getPositionAlignment() const {
		return _positionAlignment;
	}
	
	AxisAlignment getAxisAlignment() const {
		return _axisAlignment; 
	}

	double getScale() const {
		return _scale;
	}

	CoordinateAlign getCoordinateAlign() const {
		return _coordinateAlign;
	}

	//! This method should return a matrix that calculatePosition will (by default,
	//! at least, unless it has also been overridden) will use when determining the
	//! matrix.
	virtual osg::Matrix getAlignmentTransform() const;

	//! Sets the PositionAlignment enum to use for modifying the position of
	//! the Text, modifying it's absolute placement. The default PositionAlignment
	//! of POS_ALIGN_LEFT_BOTTOM however is a no-op, since it corresponds to how
	//! Pango arranges the layout by default. The recalculate argument is the
	//! same as for setPosition().
	void setPositionAlignment(PositionAlignment alignment, bool recalculate = true) {
		_positionAlignment = alignment;

		if(recalculate) calculatePosition();
	}
	
	void setAxisAlignment(AxisAlignment alignment, bool recalculate = true) {
		_axisAlignment = alignment;
		
		if(recalculate) calculatePosition();
	}
	
	void setScale(osg::Vec3::value_type scale, bool recalculate = true) {
		_scale = scale;
		
		if(recalculate) calculatePosition();
	}

	void setCoordinateAlign(CoordinateAlign align) {
		_coordinateAlign = align;
	}

protected:


	PositionAlignment     _positionAlignment;
	AxisAlignment         _axisAlignment;
	osg::Vec3::value_type _scale;
	osg::Matrix           _lastTransform;
	CoordinateAlign       _coordinateAlign;
};

}

#endif
